package com.googlecode.cswish.struts.conversion;

import java.lang.reflect.Member;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.googlecode.cswish.util.FrameConstant;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.conversion.TypeConverter;
import com.opensymphony.xwork2.conversion.impl.XWorkConverter;

/**
 * This is a temporary class to resolve a xwork defect<br>
 * Fix a dead cycle error -- http://jira.opensymphony.com/browse/XW-592
 * 
 * @author Jerry.Feng 2008-10-18
 */
public class CSwishBasicConverter extends XWorkConverter {

	private static final Log logger = LogFactory.getLog(CSwishBasicConverter.class);
	
	// FIXME: move the detail conversion logic to BooleanConverter, DoubleConverter etc
	@Override
	public Object convertValue(Map context, Object target, Member member, String property, Object value, Class toClass) {
		if (value instanceof Object[]) {
			if (((Object[])value).length == 0) {
				return null;
			}
		} else if (value instanceof Collection) {
			if (((Collection)value).size() == 0) {
				return null;
			}
		}
		if (context == null) {
			ActionContext ctx = ActionContext.getContext();
			if (ctx != null) {
				context = ctx.getContextMap();
			} else {
				context = new HashMap();
			}
		}
		
		// save the property to facilitate the conversion class 
		if (property != null) {
			context.put(FrameConstant.CONVERTER_PROPERTY, property);
		}
		
		if (Number.class.isAssignableFrom(toClass)) {
			String val = null;
			if (value instanceof String) {
				val = (String) value;
			} else if (value instanceof String[]) {
				String[] theVal = (String[]) value;
				if (theVal.length == 1) {
					val = theVal[0];
				}
			}
			// skip the special char
			if (val != null) {
				StringBuilder sb = new StringBuilder(val.length());
				for (int i = 0, len = val.length(); i < len; i++) {
					char c = val.charAt(i);
					if (c == '-' || c == '.' || Character.isDigit(c)) {
						sb.append(c);
					}
				}
				value = sb.toString();
			}
		} else if (Boolean.class.isAssignableFrom(toClass)) {
			if (value.getClass().isEnum()) {
	        	int val = ((Enum)value).ordinal();
	        	if (val == 0) {
	        		return null;
	        	} else if (val == 1) {
	        		return Boolean.TRUE;
	        	} else if (val == 2) {
	        		return Boolean.FALSE;
	        	} else {
	        		return null;
	        	}
	        } else if (value instanceof String) {
	        	String val = (String)value;
	        	if ("1".equals(val) || "Y".equals(val) || "true".equals(val)) {
	        		return Boolean.TRUE;
	        	} else if ("2".equals(val) || "N".equals(val) || "false".equals(val)) {
	        		return Boolean.FALSE;
	        	} else {
	        		return null;
	        	}
	        }
		}
		Object ret = super.convertValue(context, target, member, property, value, toClass);
		if (ret == TypeConverter.NO_CONVERSION_POSSIBLE) {
			if (logger.isDebugEnabled()) {
				logger.debug("Failed to convert value to target type: " + toClass + ", " + value);
			}
			ret = null;
		}
		return ret;
	}
	
	@Override
	public Object convertValue(Object value, Class toType) {
		Object ret = super.convertValue(null, value, toType);
		return ret;
	}
}